#pragma once
#include<iostream>
#include <stdarg.h>
#include<fstream>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>


#define Screen 1
#define OneFile 2
#define ClassFile 3


#define Info 1
#define Warning 2
#define Error 3
#define Debug 4
#define Fatal 5

#define SIZE 1024

#define LogFile "log.txt"




class Log
{
public:
    Log()
        :_printmethod(Screen),_path("./log/")
    {}

    void enable(int printmethod)
    {
        _printmethod = printmethod;
    }

    std::string levelToString(int level)
    {
        switch(level)
        {
            case Info:
                return "Info";
            case Warning:
                return "Warning";
            case Error:
                return "Error";
            case Debug:
                return "Debug";
            case Fatal:
                return "fatal";
            default :
                return "";
        }
        return "";
    }

    void operator()(int level,const char* format,...)
    {
        //将固定信息转入左字符串
        time_t t = time(nullptr);
        struct tm* ptime = localtime(&t);
        char leftbuffer[SIZE];
        snprintf(leftbuffer,SIZE,"[%s]:[%d-%d-%d %d:%d:%d]",levelToString(level).c_str(),ptime->tm_year + 1900,
        ptime->tm_mon + 1,ptime->tm_mday,ptime->tm_hour,ptime->tm_min,ptime->tm_sec);

        //将自定义信息转入右字符串
        char rightbuffer[SIZE];
        va_list s;
        va_start(s,format);
        //因为是外部输入自定义信息，由他自己判断输入即可，我们只需要给可变参数开始位置即可。
        vsnprintf(rightbuffer,SIZE,format,s);
        va_end(s);

        char logtxt[SIZE*2];
        //拼接上固定与自定义信息成为我们的日志信息
        int n = snprintf(logtxt,SIZE*2,"%s %s",leftbuffer,rightbuffer);
        logtxt[n] = '\n';
        logtxt[n+1] = '\0';
        //打印我们的日志
        printLog(level,logtxt);

    }

    void printLog(int level,const std::string& logtxt)
    {
        switch(_printmethod)
        {
            case Screen:
                std::cout << logtxt;
                break;
            case OneFile:
                printOneFile(LogFile,logtxt);
                break;
            case ClassFile:
                printClassFile(level,logtxt);
                break;
        }
    }


    void printOneFile(const char* logfile,const std::string& logtxt)
    {
        //拼接路径
        std::string _logfile = _path + logfile;
        //利用c++文件流打开文件
        // std::ofstream ofs("log.txt");

        // //由于string重载了operator<<,因此我们可以直接输出到文件里面。
        // ofs << logtxt;
        int fd = open(_logfile.c_str(),O_WRONLY|O_CREAT|O_APPEND,0666);
        if(fd < 0)
        {
            perror("print open");
            return;
        }

        write(fd,logtxt.c_str(),logtxt.size());
        close(fd);
    }
    
    void printClassFile(int level,const std::string& logtxt)
    {
        //创建并且拼接我们的日志文件名字
        std::string logfile = LogFile;
        logfile += ".";
        logfile += levelToString(level);
        //分类后再服用打印到一个文件里面的函数
        printOneFile(logfile.c_str(),logtxt);
    }



private:
    int _printmethod;
    std::string _path;
};

Log lg;
